package xuecheng.tool.logservice.alibaba;

import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.collect.Lists;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.CharsetUtil;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

/***
 * 阿里日志查询分析任务基类*
 * <p/>
 * **
 *
 * @author PengXueCheng
 * @version 1.0.0
 **/
@Slf4j
public abstract class BaseAliLogTask<T> {

    @Autowired
    protected AliLogUtils aliLogUtils;
    @Autowired
    protected LogProperties logProperties;

    /**
     * 执行任务
     *
     * @param param
     *            任务参数
     */
    public void execute(String param) {
        String taskDesc = getTaskDesc();
        log.info("{}开始...", taskDesc);
        QueryEntity<T> queryEntity = getQueryEntity(param);
        @NonNull
        String project = logProperties.getProject();
        String logstore = logProperties.getLogstores().get(queryEntity.getLogstore());
        Date fromTime = queryEntity.getFromTime();
        Date toTime = queryEntity.getToTime();
        aliLogUtils.analyze(project, logstore, fromTime, toTime, queryEntity.getQuery(), queryEntity.getTClass(),
            (AliLogUtils.CallBack<T>)list -> Lists.partition(list, 1000).stream().forEach(this::updateData));
        log.info("{}执行成功!!!", taskDesc);
    }

    /**
     * 读取查询语句文件, 获取查询语句字符串
     *
     * @param querySqlFilePath
     *            user query(查询分析语句)文件所在路径, 必须放在 resource 目录下. 例如: alilog-analyze/xxx.sql
     * @return 查询语句字符串
     */
    protected String getQuery(String querySqlFilePath) {
        return IoUtil.read(ResourceUtil.getReader(querySqlFilePath, CharsetUtil.CHARSET_UTF_8));
    }

    /**
     * 当查询分析得到得到数据时调用
     *
     * @param ts
     *            查询分析数据集
     */
    protected abstract void updateData(List<T> ts);

    /**
     * 获取查询实体
     *
     * @param param
     *            任务参数
     * @return 查询实体
     */
    protected abstract QueryEntity<T> getQueryEntity(String param);

    /**
     * 获取任务描述
     *
     * @return
     */
    protected abstract String getTaskDesc();

    /**
     * 查询实体
     *
     * @param <T>
     */
    @Getter
    @ToString
    protected static class QueryEntity<T> {

        /**
         * 项目中使用的日志库名称(非阿里云日志库名称)
         */
        private String logstore;

        /**
         * begin time(精度为秒)
         */
        private Date fromTime;

        /**
         * end time(精度为秒)
         */
        private Date toTime;

        /**
         * user query(查询分析语句)
         */
        private String query;

        /**
         * topic name of a log store
         */
        private String topic;

        /**
         * 分析结果集行数据映射实体字节码
         */
        private Class<T> tClass;

        /**
         *
         * @param logstore
         *            项目中使用的日志库名称(非阿里云日志库名称)
         * @param fromTime
         *            begin time(精度为秒)
         * @param toTime
         *            end time(精度为秒)
         * @param query
         *            user query(查询分析语句)
         * @param topic
         *            topic name of a log store
         * @param tClass
         *            分析结果集行数据映射实体字节码
         */
        public QueryEntity(String logstore, Date fromTime, Date toTime, String query, String topic, Class<T> tClass) {
            this.logstore = logstore;
            this.fromTime = fromTime;
            this.toTime = toTime;
            this.query = query;
            this.topic = topic;
            this.tClass = tClass;
        }

        /**
         *
         * @param logstore
         *            项目中使用的日志库名称(非阿里云日志库名称)
         * @param fromTime
         *            begin time(精度为秒)
         * @param toTime
         *            end time(精度为秒)
         * @param query
         *            user query(查询分析语句)文件所在路径
         * @param tClass
         *            分析结果集行数据映射实体字节码
         */
        public QueryEntity(String logstore, Date fromTime, Date toTime, String query, Class<T> tClass) {
            this(logstore, fromTime, toTime, query, "", tClass);
        }
    }
}
